#include "sem.h"
#include "task.h"
#include "types.h"

void sem_init(sem_t *sem, int init_count)
{
    sem->count = init_count;
    list_init(&sem->wait_list);
}
void sem_wait(sem_t *sem)
{
    irq_state_t irq_state = irq_enter_protect();
    if (sem->count > 0)
    {
        sem->count--;
    }
    else
    {
        task_t *current_task = task_current_task();
        task_set_block(current_task);
        list_insert_last(&sem->wait_list, &current_task->wait_node);
        task_dispatch();
    }
    irq_exit_protect(irq_state);
}
void sem_notify(sem_t *sem)
{
    irq_state_t irq_state = irq_enter_protect();
    if (list_empty(&sem->wait_list))
    {
        sem->count++;
    }
    else
    {
        list_node_t *node = list_remove_first(&sem->wait_list);
        task_t      *task = container_of(node, task_t, wait_node);
        task_set_ready(task);
        task_dispatch();
    }
    irq_exit_protect(irq_state);
}

int sem_count(sem_t *sem)
{
    irq_state_t irq_state = irq_enter_protect();
    int         count     = sem->count;
    irq_exit_protect(irq_state);
    return count;
}
